<?php

/**
 * User: Z.kc <273816036@qq.com>
 * Date: 2017-06-02 10:22
 */


namespace FastDFS;

/**
 * 参照 http://php.net/manual/en/class.streamwrapper.php
 *
 */
class Stream {

	/**
	 * @var int 当前位置
	 */
	var $position;

	/**
	 * @var resource 流
	 */
	var $stream;

	/**
	 * @var Storage 保持资源用
	 */
	var $storage;

	/**
	 * @var int 总长度
	 */
	var $length;

	protected function getTracker() {
		return new Tracker('127.0.0.1', 22122);
	}

	protected function getStorage($host, $port) {
		return new Storage($host, $port);
	}

	/**
	 * @param $path
	 *
	 * @return array(Storage, string, string)
	 * @throws Exception
	 */
	private function getFileStorage($path) {
		$url   = parse_url($path);
		$group = $url["host"];

		$tracker = $this->getTracker();

		$storage_info = $tracker->applyStorage($group);

		$storage = $this->getStorage($storage_info['storage_addr'], $storage_info['storage_port']);

		$path = ltrim($url['path'], '/');

		$path = str_replace('//', '/', $path);

		// xxx 必须保持, 否则stream释放了
		$this->storage = $storage;

		return [
			$storage,
			$group,
			$path,
		];
	}

	function stream_open($path, $mode, $options, &$opened_path) {
		try {
			list($storage, $group, $path) = $this->getFileStorage($path);

			$this->position = 0;
			$ret            = $storage->readStream($group, $path);

			if (is_array($ret)) {
				$this->stream = &$ret['stream'];
				$this->length = $ret['length'];

				return true;
			}

		} catch (\Exception $e) {
			if ($options & STREAM_REPORT_ERRORS == STREAM_REPORT_ERRORS) {
				throw $e;
			} else {
				return false;
			}
		}

		return false;
	}

	function stream_read($count) {
		//$ret = stream_get_contents($this->storage->_sock, $count);//fread($this->stream, $count);
		//echo ftell($this->stream);
		if ($count + $this->position > $this->length) {
			$count = $this->length - $this->position;
		}

		if ($count <= 0) {
			return '';
		}

		$ret = fread($this->stream, $count);
		$this->position += strlen($ret);

		return $ret;
	}

	function stream_write($data) {
		throw new \Exception('不支持写操作');
	}

	function stream_tell() {
		return $this->position;
	}

	function stream_eof() {
		return $this->position >= $this->length;
	}

	function stream_close() {
		$this->storage = null;
		$this->stream  = null;

		return true;
	}

	function stream_seek($offset, $whence) {
		return false;
	}

	function stream_metadata($path, $option, $var) {
		return false;
	}

	function stream_stat() {
		return [];
	}

	function url_stat($path, $flags) {

		list($storage, $group, $path) = $this->getFileStorage($path);

		$file_info = $storage->getFileInfo($group, $path);

		if ($file_info === false) {
			return false;
		}

		$stat_info = [
			'dev'     => 0,
			'ino'     => 0,
			'mode'    => 0100000 + 0777,
			'nlink'   => 0,
			'uid'     => getmyuid(),
			'gid'     => getmygid(),
			'rdev'    => 0,

			'size'    => $file_info['file_size'],
			'atime'   => $file_info['timestamp'],
			'mtime'   => $file_info['timestamp'],
			'ctime'   => $file_info['timestamp'],

			'blksize' => 0,
			'blocks'  => 0,
		];

		return $stat_info;
	}
}


//stream_wrapper_register('fastdfs', '\FastDFS\Stream', STREAM_IS_URL);
//stream_wrapper_register('fastdfs', \FastDFS\Stream::class, STREAM_IS_URL);
